package com.ycwl.aiLive_2d.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ycwl.aiLive_2d.thread.MouthThreadPoolExecutor;
import com.ycwl.aiLive_2d.ai_model_api.wxChatRobot.service.RobotInstance;
import com.ycwl.aiLive_2d.exception.BaseException;
import com.ycwl.aiLive_2d.service.GlobalService;
import com.ycwl.aiLive_2d.utils.ApiResponse;
import com.ycwl.aiLive_2d.utils.FileSplitUtils;
import com.ycwl.aiLive_2d.utils.HttpUtils;
import com.ycwl.aiLive_2d.utils.SnowFlakeUtil;
import com.ycwl.aiLive_2d.utils.jwtUtils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

import static com.ycwl.aiLive_2d.thread.MouthThreadReturnByThreadPool.*;


/**
 * @author songmingsong
 * @date 2023/6/14
 */
@Slf4j
@Service
public class GlobalServiceImpl implements GlobalService {
    @Value("${wxChatBot.token}")
    String token;
    @Value("${baiduServerApi.tts}")
    String ttsUrl;
    @Value("${chatServerApi.url}")
    String chatBaseUrl;

    @Autowired
    JwtTokenUtil jwtTokenUtil;

    @Override
    public ApiResponse dialogue(String msg, String uid) {
        // 调用微信开放对话平台代码（注释）
        //String answer = RobotInstance.getInstance(token).answer(msg);

        String chatUrl = chatBaseUrl + msg;
        HttpUtil.get(chatUrl);
        String chatServerResult = HttpUtil.get(chatUrl);
        JSONObject chatServerJsonObject = (JSONObject) JSON.parse(chatServerResult);
        Integer code = (Integer) chatServerJsonObject.get("code");
        if (code != 200) {
            log.error("调用chatBot异常");
            throw new BaseException("获取回答异常", 5001);
        }
        String answer = (String) chatServerJsonObject.get("data");

        String wavPath = this.getClass().getResource("/").toString();
        if (wavPath.startsWith("file:")) {
            wavPath = wavPath.substring("file:/".length());
        }
        if (uid.equals("1")) {
            uid = SnowFlakeUtil.getId();
        }
        /**
         * 创建文件夹
         */
        File audioFile = new File(wavPath + uid);
        if (!audioFile.exists() && !audioFile.mkdirs()) {
            log.error("文件存储异常");
            throw new BaseException("文件存储异常", 5001);
        }
        String savePath = wavPath + uid + "/streaming_tts.wav";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("text", answer);
        params.put("spk_id", 0);
        params.put("speed", 1.0);
        params.put("volume", 1.0);
        params.put("sample_rate", 0);
        params.put("save_path", savePath);
        File file = new File(savePath);
        if (file.exists()) {
            file.delete();
        }

        String httpResult = HttpUtils.sendPost(ttsUrl, params);
        JSONObject jsonObject = (JSONObject) JSON.parse(httpResult);
        Boolean success = (Boolean) jsonObject.get("success");
        if (Boolean.FALSE.equals(success)) {
            log.error("语音转换异常");
            throw new BaseException("语音转换异常", 5001);
        }

        /**
         * 启动线程解析语音数据
         */
        String splitFilePath = wavPath + uid;
        String copyFilePath = splitFilePath + "/streaming_tts_copy.wav";
        try {
            FileSplitUtils.copyFiles(savePath, copyFilePath);
        } catch (IOException e) {
            log.error("文件拷贝异常");
            throw new BaseException("文件拷贝异常", 5001);
        }
        MouthThreadPoolExecutor.startPase(splitFilePath, copyFilePath, uid);

        Map<String, Object> resultVO = new HashMap<String, Object>();
        //JSONObject result = (JSONObject) jsonObject.get("result");
        //Object audio = result.get("audio");
        //resultVO.put("audio", audio));// 语音BASE64编码
        resultVO.put("answer", answer);// AI回答
        resultVO.put("uid", uid);// 用户ID

        // 正在解析口型
        isPaseMap.put(uid, "前");
        return ApiResponse.buildSuccessResponse(resultVO);
    }

    @Override
    public ApiResponse getMouthList(String uid) {
        String isPase = isPaseMap.get(uid);
        List<Double> resultDoubleVO = new ArrayList<>();
        Map<String, Object> resultVO = new HashMap<>();
        /**
         * 使 “后” 的状态只出现一次
         */
        if (isPase != null && isPase.equals("后")) {
            resultVO.put("isPase", isPase);
            resultVO.put("data", resultDoubleVO);
            isPaseMap.put(uid, "前");
            return ApiResponse.buildSuccessResponse(resultVO);
        }
        LinkedList<Map<Integer, List<Double>>> data = (LinkedList) queueMap.get(uid);
        if (Objects.isNull(data)) {
            isPase = "前";
        } else {
            Set<Integer> allKey = new HashSet<>(); // 存放所有key

            for (int k = 0; k < data.size(); k++) {
                Map<Integer, List<Double>> peek = data.get(k); // 检查
                if (Objects.isNull(peek)) {
                    isPase = "后";
                } else {
                    Set<Integer> integers = peek.keySet();
                    allKey.add(new ArrayList<>(integers).get(0));
                }
            }
            if (!allKey.contains(0)) {
                // 第一段数据还没有解析出来
                isPase = "前";
            } else if (!allKey.contains(0) && allKey.size() < 5) {
                // 所有片段数据还没有解析出来(除开不切片解析数据的情况)
                isPase = "前";
            } else {
                // 排列所有数据
                Map<Integer, List<Double>> allMap = new HashMap<>(); // 存放所有数据
                int size = data.size();
                for (int k = 0; k < size; k++) {
                    Map<Integer, List<Double>> datum = data.poll(); // 取出并移除
                    Set<Integer> keySet = datum.keySet();
                    ArrayList<Integer> keyList = new ArrayList<>(keySet);
                    Integer keyByAll = keyList.get(0);
                    allMap.put(keyByAll, datum.get(keyByAll));
                }
                for (Integer key : allKey) {
                    List<Double> doubles = allMap.get(key);
                    resultDoubleVO.addAll(doubles);
                    isPase = "中";
                    isPaseMap.put(uid, "后");
                }
            }

        }
        resultVO.put("isPase", isPase);
        resultVO.put("data", resultDoubleVO);
        return ApiResponse.buildSuccessResponse(resultVO);
    }


    @Override
    public void getAudio(HttpServletResponse response, String uid) {
        downLoadFile(response, uid);
    }

    public void downLoadFile(HttpServletResponse response, String uid) {
        String wavPath = this.getClass().getResource("/").toString();
        // 文件地址的全路径
        String httpUrl = wavPath + uid + "/streaming_tts.wav";
        ServletOutputStream out = null;
        try {
            // 与服务器建立连接
            URL url = new URL(httpUrl);
            URLConnection conn = url.openConnection();
            InputStream inputStream = conn.getInputStream();
            try {
                response.setHeader("Content-Disposition", "attachment; filename=\"audio.wav\"");
                response.setContentType("multipart/form-data");
            } catch (Exception e) {
                e.printStackTrace();
            }
            out = response.getOutputStream();
            // 读取文件流
            int len = 0;
            byte[] buffer = new byte[1024 * 10];
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
